package cn.duhengkui.national.valuelist.masterslavedb;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.sql.DataSource;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Component;

import cn.duhengkui.national.valuelist.annotation.DataSourceType;
import cn.duhengkui.national.valuelist.context.DBContextHolder;

@Component
public class ValuelistDataSource extends AbstractRoutingDataSource implements ApplicationContextAware{
	
	private Object master;
	
	private boolean onlyMaster = false;
	
	//private Map<Object, Object> slaves;
	
	private ApplicationContext applicationContext;
	

/*	public void setMaster(Object master) {
		this.master = master;
	}*/

	public boolean isOnlyMaster() {
		return onlyMaster;
	}


	private List<Object> slaveList = new Vector<>();

	/*@Nullable
	public void setSlaves(Map<Object, Object> slaves) {
		this.slaves = slaves;
	}	*/	


	@Override
	protected Object determineCurrentLookupKey() {
		Object result = null;
		if(DBContextHolder.getContextHolder() == null){
			DBContextHolder.setContextHolder(DataSourceType.Type.Write);
		}
		if(DBContextHolder.getContextHolder().equals(DataSourceType.Type.Read)){
			if(slaveList.size() > 0){
				result = slaveList.get(0);
				slaveList.remove(0);
				slaveList.add(result);
			}else{
				result =master;
			}
		}else if(DBContextHolder.getContextHolder().equals(DataSourceType.Type.Write)){
			 result = master;
		}else{
			throw new RuntimeException();
		}
		return result;
	}
	
	protected DataSource determineTargetDataSource() {
		return super.determineTargetDataSource();
	}
	
	@Override
	public void afterPropertiesSet() {
		 Map<String, DataSource> dataSources = applicationContext.getBeansOfType(DataSource.class);
		 
		 Map<Object, Object> targetDataSource = excludeCurrentDataSource(dataSources);
		 if (targetDataSource.size() == 0) {
             throw new IllegalStateException("Datasource can not found!!!");
         }
         setTargetDataSources(targetDataSource);
         
		if(targetDataSource.size() >= 1){
			int index = 0;
			for(Object key : targetDataSource.keySet()){
				if(index == 0){
					master = key;
				}else{
					slaveList.add(key);
				}
				index++;
			}
			if(targetDataSource.size() == 1){
				onlyMaster = true;
			}
		}
		super.afterPropertiesSet();
	}
	
	private LinkedHashMap<Object, Object> excludeCurrentDataSource(Map<String, DataSource> dataSources) {
		LinkedHashMap<Object, Object> targetDataSource = new LinkedHashMap<>();
        Iterator<String> keys = dataSources.keySet().iterator();
        while (keys.hasNext()) {
            String key = keys.next();
            if (!(dataSources.get(key) instanceof ValuelistDataSource)) {
                targetDataSource.put(key, dataSources.get(key));
            }
        }
        return targetDataSource;
    }

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
		
	}

}
